@echo off
:: chcp 437 >nul & graftabl 936 >nul
md tmp 2>nul
more +24 %0 > tmp\%~n0.cpp
if not "%1"=="debug" (
set coptimize=-O3 -msse -msse2 -ffast-math
set cxxoptimize=-Wno-invalid-offsetof -msse -msse2 -O3 -ftree-vectorize -funsafe-math-optimizations -ffast-math -fomit-frame-pointer -funsafe-loop-optimizations
) else (
set coptimize=-Wall -g -DDEBUG
set cxxoptimize=-Wno-invalid-offsetof -msse -msse2 -Wall -g -DDEBUG
)
g++ -c -o tmp\conxlat.o conxlat.cpp %cxxoptimize%
g++ -c -o tmp\%~n0.o tmp\%~n0.cpp %cxxoptimize%

g++ tmp\*.o -o %~n0.exe -Wl,-Bstatic -static-libgcc -static-libstdc++ -mwindows
:: rd /s /q tmp
if not "%1"=="debug" (
strip %~n0.exe
)
:: %~n0.exe

pause
goto :eof

#include <tchar.h>
#include <windows.h>
#include <set>
#include "../console-struct.h"
#include "../ascii-font-ex.h"

#define ATOM_TO_LPTSTR(a) (LPCTSTR)((LONG_PTR)(a))
#define FMAP_LEN 120
#define USR_REPAINT (WM_USER + 0)

#ifndef NT_SUCCESS
#define NT_SUCCESS(a) ((LONG)(a) >= 0)
#endif 

#ifdef __GNUC__
#define REGPARM(n)  __attribute__ ((regparm(n), noinline))
#define REALIGNED   __attribute__ ((force_align_arg_pointer))
#define LIKELY(x)   __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define REGPARM(n)
#define REALIGNED
#define LIKELY(x)   x
#define UNLIKELY(x) x
#endif

class WProc
{
public:
	static void REGPARM(3) Entry (LPCTSTR, HINSTANCE, int, char**, int, int);
	static LRESULT REALIGNED __stdcall MainWinProc(HWND, UINT, WPARAM, LPARAM);

private:
	static std::set<HWND> hwndSet;
	struct Params
	{
		DWORD dwWidth;
		DWORD dwHeight;
		LPVOID lpvCallback;
		HBITMAP bmp;
		HDC cdc;
		PVOID bits;
		_CHAR_DATA * buffer;
	};
	static HBITMAP REGPARM(2) CreateBmp(HDC, Params *);
	static BOOL REGPARM(2) CreateWinProc(HWND, LPARAM);
	static LRESULT __declspec(noinline) PrivateWinProc(HWND, UINT, WPARAM, LPARAM);
	static void Repaint();
	static void REGPARM(1) Repaint(HWND);
	static void __fastcall TranslateMap(HWND, Params *);
};

fontdata_t *ascii_font_ptr = NULL;

void sdl_translate_map(_CHAR_DATA* text_buf, unsigned int * vid, int flags);

std::set<HWND> WProc::hwndSet;

HBITMAP WProc::CreateBmp
(
	HDC hdc,
	Params * args
)
{
	BITMAPINFO bi;
	memset(&bi, 0, sizeof(bi));
	bi.bmiHeader.biSize			= sizeof( bi.bmiHeader );
	bi.bmiHeader.biBitCount		= sizeof( DWORD ) * 8;
	bi.bmiHeader.biCompression	= BI_RGB;
	bi.bmiHeader.biPlanes		= 1;
	bi.bmiHeader.biWidth		= args->dwWidth;
	bi.bmiHeader.biHeight		= -args->dwHeight;
	return CreateDIBSection( hdc, &bi, DIB_RGB_COLORS, &args->bits, NULL, 0 );
}

BOOL WProc::CreateWinProc
(
	HWND hwnd,
	LPARAM lParam
)
{
	Params *args;
	HBITMAP bmp;
	HDC cdc, hdc;
	
	hwndSet.insert(hwnd);
	if (UNLIKELY(!(hdc = GetDC(hwnd))))
		return FALSE;
	if (UNLIKELY(!(cdc = CreateCompatibleDC(hdc))))
		goto fail_create_cdc;
	args = (Params *)((CREATESTRUCTA*)lParam)->lpCreateParams;
	if (UNLIKELY(!(bmp = CreateBmp(hdc, args))))
		goto fail_create_bmp;
	if (UNLIKELY((args->bmp = (HBITMAP)SelectObject(cdc, bmp)) == NULL))
		goto fail_select_bmp;
	args->cdc = cdc;
	SetLastError(0);
	SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)args);
	if (UNLIKELY(GetLastError() != 0))
	{
		SelectObject(cdc, args->bmp);
	fail_select_bmp:
		DeleteObject(bmp);
	fail_create_bmp:
		DeleteDC(cdc);
	fail_create_cdc:
		ReleaseDC(hwnd, hdc);
		return FALSE;
	}
	ReleaseDC(hwnd, hdc);
	return TRUE;
}

void WProc::Entry
(
	LPCTSTR lpszClassName,
	HINSTANCE hInst,
	int argc,
	char ** argv, 
	int w,
	int h
)
{
	HANDLE hMapFile;
	HMODULE hNtdll;
	HWND hwnd;
	Params hwnd_args;
	MSG msg;
	_CHAR_DATA * pMapBuffer;

	hwnd_args.dwWidth = w;
	hwnd_args.dwHeight = h;
	hwnd_args.lpvCallback = (LPVOID)TranslateMap;
	
	if (argc < 2)
		return;
	else
	{
		char fm_name[FMAP_LEN] = "MYCON_";
		size_t fm_pfxl = strlen(fm_name);
		size_t fm_argl = FMAP_LEN - 1 - fm_pfxl;
		strncpy(fm_name + fm_pfxl, argv[1], fm_argl);
		fm_name[FMAP_LEN-1] = '\0';
		
		hMapFile = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, TRUE, fm_name);
	}
	
	if (!(ascii_font_ptr = (fontdata_t *)calloc(FONT_NUM_CHARS, sizeof(intptr_t))))
		goto fail_1;
	
	for (int i = 0; i < 95; i++)
		ascii_font_ptr[i+32] = (fontdata_t)ascii_font[i];
	
	struct _STATUS_DATA_1 {
		int64_t tHandle;	// 8-byte
		int64_t tHandleMutex;	// 8-byte
		int statusf[2];
		int64_t tHwnd;	// 8-byte
	} *lpStat;

	pMapBuffer = (_CHAR_DATA *) MapViewOfFile(
		hMapFile,
		FILE_MAP_READ | FILE_MAP_WRITE,
		0, 0,
		XCHRS * YCHRS * sizeof(_CHAR_DATA) + sizeof(_STATUS_DATA_1)
	);

	if (pMapBuffer == NULL)
		goto fail_2;

	hwnd_args.buffer = pMapBuffer;	
	lpStat = (_STATUS_DATA_1 *)(&(pMapBuffer[XCHRS * YCHRS]));

	hwnd = CreateWindow(
		lpszClassName,
		_T("untitled window"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		hwnd_args.dwWidth + 2 * GetSystemMetrics(SM_CXSIZEFRAME),
		hwnd_args.dwHeight + 2 * GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION),
		NULL, NULL, hInst, &hwnd_args
	);

	if (UNLIKELY(hwnd == NULL))
		abort();
	
	if (UNLIKELY(!(hNtdll = LoadLibrary("ntdll.dll"))))
	{
		DestroyWindow(hwnd);
		goto fail_3;
	}
	else
	{
		int __stdcall (*fAlertThread)(HANDLE) = (int __stdcall (*)(HANDLE)) GetProcAddress(hNtdll, "NtAlertThread");
		void __stdcall (*fRaiseStatus)(int) = (void __stdcall (*)(int)) GetProcAddress(hNtdll, "RtlRaiseStatus");

		lpStat->tHwnd = (int64_t)hwnd;
#ifdef __GNUC__
		__asm__ __volatile__ ("" ::: "memory");
		if (__sync_bool_compare_and_swap(&(lpStat->statusf[0]), 0, 1))
#else
		if (InterlockedCompareExchange(&(lpStat->statusf[0]), 1, 0) == 0)
#endif
		{
			if (LIKELY(
				(HANDLE)(lpStat->tHandle) != NULL &&
				fAlertThread != NULL &&
				fRaiseStatus != NULL
			))
			{
				int status = fAlertThread((HANDLE)(lpStat->tHandle));
				if (UNLIKELY(!NT_SUCCESS(status)))
				{
					fRaiseStatus(status);
				}
				// lpStat->status = 2;
			}
			else
				abort();
		}
	}
	
	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);
	msg.message = 0;

	while ( (msg.message != WM_QUIT) )
	{
		if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) != 0 )
		{
			TranslateMessage (&msg);
			DispatchMessage (&msg);
		}
		else
		{
			Repaint();
			Sleep(20);
		}
	}
	/* Do NOT call DestroyWindow here. */

	FreeLibrary(hNtdll);
fail_3:
	UnmapViewOfFile(pMapBuffer);
fail_2:
	free(ascii_font_ptr);
fail_1:	
	CloseHandle(hMapFile);
}

LRESULT WProc::MainWinProc
(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{
	Params *args;
	BOOL bRet;
	// RWLOCK l;
	
	if (uMsg >= WM_USER)
	{
		if (LIKELY(uMsg <= 0x7FFF))
			return WProc::PrivateWinProc (hwnd, uMsg, wParam, lParam);
		goto app_message;
	}

	switch (uMsg)
	{
	case WM_CREATE:
		// EXCLUSIVE_LOCK_ACQUIRE(l);
		bRet = CreateWinProc(hwnd, lParam);
		// EXCLUSIVE_LOCK_RELEASE(l);
		if (UNLIKELY(bRet == FALSE))
			return -1;
		break;
	case WM_DESTROY:
		// EXCLUSIVE_LOCK_ACQUIRE(l);
		*(LONG_PTR *)&args = GetWindowLongPtr( hwnd, GWLP_USERDATA );
		if (LIKELY(args != NULL))
		{
			HDC cdc = args->cdc;
			DeleteObject(SelectObject(cdc, args->bmp));
			DeleteDC(cdc);
		}
		hwndSet.erase(hwnd);
		if (hwndSet.empty())
			PostQuitMessage(0);
		// EXCLUSIVE_LOCK_RELEASE(l);
		return 0;
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			*(LONG_PTR *)&args = GetWindowLongPtr( hwnd, GWLP_USERDATA );
			HDC hdc = BeginPaint( hwnd, &ps );
			if (UNLIKELY(hdc == NULL))
				abort();
			if (args->lpvCallback != NULL)
				((void __fastcall (*) (HWND, PVOID)) args->lpvCallback) (hwnd, args);
			BitBlt( hdc, 0, 0, args->dwWidth, args->dwHeight, args->cdc, 0, 0, SRCCOPY );
			EndPaint( hwnd, &ps );
		}
		return 0;
	}
app_message:
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

LRESULT WProc::PrivateWinProc
(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{
	switch (uMsg)
	{
	case USR_REPAINT:
		if (wParam & 1)
		{
			// SHARED_LOCK_ACQUIRE(l);
			for (std::set<HWND>::iterator it = hwndSet.begin(); it != hwndSet.end(); ++it)
				Repaint(*it);
			// SHARED_LOCK_RELEASE(l);
		}
		else
			Repaint(hwnd);
	}
	return 0;
}

void WProc::Repaint ()
{
	PrivateWinProc (NULL, USR_REPAINT, 1, 0);
}

void WProc::Repaint
(
	HWND hwnd
)
{
	InvalidateRect(hwnd, NULL, FALSE);
	UpdateWindow(hwnd);
}

void WProc::TranslateMap
(
	HWND hwnd,
	Params * lpParam
)
{
	sdl_translate_map(lpParam->buffer, (unsigned int *)lpParam->bits, 0);
}

int main (int argc, char** argv)
{
	LPCTSTR class_name = _T("TEST_WINDOW"), class_atom;
	HBRUSH hbrush;
	WNDCLASS wc;

	if (UNLIKELY(!(hbrush = CreateSolidBrush(0x000000))))
		return 1;

	wc.style = 0;
	wc.lpfnWndProc = WProc::MainWinProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = GetModuleHandle(NULL);
	wc.hIcon = NULL;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = hbrush; // default: (HBRUSH)(COLOR_BTNFACE + 1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = class_name;

	if (UNLIKELY(!(class_atom = ATOM_TO_LPTSTR(RegisterClass(&wc)))))
	{
		DeleteObject(hbrush);
		return 1;
	}
	
	WProc::Entry(class_atom, wc.hInstance, argc, argv, XRES, YRES);

	UnregisterClass(class_atom, wc.hInstance);
	return 0;
}
